package com.pactera.madp.cp.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pactera.madp.common.core.exception.CheckedException;
import com.pactera.madp.common.core.util.R;
import com.pactera.madp.cp.api.dto.medium.MediumGroupDTO;
import com.pactera.madp.cp.api.dto.medium.MediumGroupLevel2AddDTO;
import com.pactera.madp.cp.api.entity.BaseEntity;
import com.pactera.madp.cp.api.entity.WorkEmployeeEntity;
import com.pactera.madp.cp.api.entity.medium.MediumEnyity;
import com.pactera.madp.cp.api.entity.medium.MediumGroupDepartmentEntity;
import com.pactera.madp.cp.api.entity.medium.MediumGroupEntity;
import com.pactera.madp.cp.api.dto.medium.MediumGroupAddDTO;
import com.pactera.madp.cp.api.dto.medium.MediumGroupUpdateDTO;
import com.pactera.madp.cp.api.feign.RemoteDeptService;
import com.pactera.madp.cp.api.vo.medium.MediumGroupVO;
import com.pactera.madp.cp.handler.CorpContextHolder;
import com.pactera.madp.cp.mapper.medium.MediumGroupMapper;
import com.pactera.madp.cp.service.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: Huayu
 * @time: 2020/12/4 18:54
 */
@Service
public class MediumGroupServiceImpl extends ServiceImpl<MediumGroupMapper, MediumGroupEntity> implements IMediumGroupService {

    @Autowired
    private IMediumService mediumService;
    @Autowired
    private IWorkDeptService deptService;
    @Autowired
    private IMediumGroupDepartmentService mediumGroupDepartmentService;
    @Autowired
    private WorkEmployeeServiceImpl workEmployeeService;
    @Autowired
    private RemoteDeptService remoteService;

    @Override
    public List<MediumGroupEntity> getMediumGroupsById(String ids) {
        QueryWrapper<MediumGroupEntity> mediumGroupEntity = new QueryWrapper<MediumGroupEntity>();
        mediumGroupEntity.select("id", "name");
        //QueryWrapper.setEntity(new CorpEntity());
        mediumGroupEntity.in("id", ids);
        return this.baseMapper.selectList(mediumGroupEntity);
    }

//    @Override
//    public List<MediumGroupEntity> getMediumGroupsByCorpId(Integer corpId) {
//        QueryWrapper<MediumGroupEntity> mediumGroupEntity = new QueryWrapper<MediumGroupEntity>();
//        mediumGroupEntity.select("id","name","visible_range");
//        mediumGroupEntity.eq("corp_id",corpId);
//        return this.baseMapper.selectList(mediumGroupEntity);
//    }

    @Override
    public List<MediumGroupEntity> getMediumGroupsByCorpId(Integer corpId) {
        return this.baseMapper.selectList(
                Wrappers.<MediumGroupEntity>lambdaQuery()
                .select(
                        MediumGroupEntity::getId,
                        MediumGroupEntity::getName,
                        MediumGroupEntity::getVisibleRange,
                        MediumGroupEntity::getDeptIds,
                        MediumGroupEntity::getCorp_id
                )
                .eq(MediumGroupEntity::getCorp_id, corpId)
                .eq(MediumGroupEntity::getParentId, 0)
        );
    }

    @Override
    public List<MediumGroupEntity> getMediumGroupByName(String name) {
        return this.baseMapper.selectList(Wrappers.<MediumGroupEntity>lambdaQuery()
                .select(MediumGroupEntity::getId)
                .eq(MediumGroupEntity::getName, name)
                .eq(MediumGroupEntity::getCorp_id, CorpContextHolder.getCorpId())
                .eq(BaseEntity::getTenantId, AccountService.getTenantId()));

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> createMediumGroup(MediumGroupAddDTO addDto) {
        if(addDto.getName() == null || "".equals(addDto.getName())) {
            throw new CheckedException("分组名称不能为空");
        }
        List<MediumGroupEntity> entities = this.baseMapper.selectList(Wrappers.<MediumGroupEntity>lambdaQuery()
                .eq(MediumGroupEntity::getName, addDto.getName())
                .eq(MediumGroupEntity::getCorp_id, CorpContextHolder.getCorpId())
                .eq(BaseEntity::getTenantId, AccountService.getTenantId())
                .eq(MediumGroupEntity::getParentId, 0)
        );
        if(!entities.isEmpty()) {
            throw new CheckedException("分组名称已存在");
        }
        Integer corpId = CorpContextHolder.getCorpId(); //获取当前企业的id 暂时注释
        MediumGroupEntity mediumGroup = new MediumGroupEntity();
        mediumGroup.setName(addDto.getName());
        mediumGroup.setCorp_id(corpId);
        mediumGroup.setVisibleRange(addDto.getVisibleRange());
        String deptIds = null;
        if (addDto.getDeptIds() != null) {
            deptIds = addDto.getDeptIds().stream().map(String::valueOf).collect(Collectors.joining(","));
        }
        mediumGroup.setDeptIds(deptIds);
        this.baseMapper.insert(mediumGroup);

        MediumGroupLevel2AddDTO addLevel2DTO = new MediumGroupLevel2AddDTO();
        addLevel2DTO.setChildren(addDto.getChildren());
        addLevel2DTO.setDeptIds(addDto.getDeptIds());
        addLevel2DTO.setParentId(mediumGroup.getId());
        addLevel2DTO.setVisibleRange(addDto.getVisibleRange());
        return saveOrUpdateGroupLevel2(addLevel2DTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> saveOrUpdateGroupLevel2(MediumGroupLevel2AddDTO addDTO) {
        MediumGroupEntity parent = this.baseMapper.selectById(addDTO.getParentId());
        if (ObjectUtil.isEmpty(parent)) {
            throw new CheckedException("操作失败，一级分组不存在");
        }
        List<String> names = new ArrayList<>();
        List<MediumGroupEntity> deletes = this.baseMapper.selectList(
                Wrappers.<MediumGroupEntity>lambdaQuery()
                .eq(MediumGroupEntity::getCorp_id, CorpContextHolder.getCorpId())
                .eq(BaseEntity::getTenantId, AccountService.getTenantId())
                .eq(MediumGroupEntity::getParentId, addDTO.getParentId())
        );
        List<Integer> deleteIds = new ArrayList<>();
        if (!deletes.isEmpty()) {
            deleteIds = deletes.stream().map(MediumGroupEntity::getId).collect(Collectors.toList());
        }

        List<MediumGroupDTO> childrens = addDTO.getChildren();
        List<MediumGroupEntity> saveOrUpdates = new ArrayList<>();
        Integer corpId = CorpContextHolder.getCorpId(); //获取当前企业的id 暂时注释

        for (int i = 0; i < childrens.size(); i++) {
            MediumGroupDTO s = childrens.get(i);
            deleteIds.remove(s.getId());
            if (names.contains(s.getName())) {
                throw new CheckedException("操作失败，将要新增的子分组已存在于当前一级分组下：" + s);
            }
            MediumGroupEntity mediumGroup = new MediumGroupEntity();
            mediumGroup.setName(s.getName());
            mediumGroup.setOrder(s.getOrder());
            mediumGroup.setId(s.getId());
            mediumGroup.setCorp_id(corpId);
            mediumGroup.setVisibleRange(addDTO.getVisibleRange());
            mediumGroup.setParentId(addDTO.getParentId());
            String deptIds = null;
            if (addDTO.getDeptIds() != null) {
                deptIds = addDTO.getDeptIds().stream().map(String::valueOf).collect(Collectors.joining(","));
            }
            mediumGroup.setDeptIds(deptIds);
            saveOrUpdates.add(mediumGroup);
        }
        if (!deleteIds.isEmpty()) {
            mediumService.remove(
                    Wrappers.<MediumEnyity>lambdaUpdate()
                    .eq(MediumEnyity::getDelFlag, 0)
                    .in(MediumEnyity::getMediumGroupId, deleteIds)
            );
            this.removeByIds(deleteIds);
        }
        if (saveOrUpdates.size() > 0) {
            this.saveOrUpdateBatch(saveOrUpdates);
        }
        return R.ok(Boolean.TRUE,"操作成功");
    }

    @Override
    public List<MediumGroupEntity> existMediumGroupByName(String name) {
        return this.baseMapper.selectList(Wrappers.<MediumGroupEntity>lambdaQuery()
                .select(MediumGroupEntity::getId).eq(MediumGroupEntity::getName, name)
                .eq(MediumGroupEntity::getCorp_id, CorpContextHolder.getCorpId())
                .eq(BaseEntity::getTenantId, AccountService.getTenantId()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R<Boolean> updateMediumGroupById(Integer corpId, MediumGroupUpdateDTO dto) {
        if(dto.getId() == null) {
            throw new CheckedException("分组id不能为空");
        }
        if(dto.getName() == null || "".equals(dto.getName())) {
            throw new CheckedException("分组名称不能为空");
        }
        List<MediumGroupEntity> mediumGroupList = this.existMediumGroupByName(dto.getName());
        List<MediumGroupEntity> linkedList = new LinkedList<>();
        for (MediumGroupEntity m : mediumGroupList) {
            if (!m.getId().equals(dto.getId())) {
                linkedList.add(m);
            }
        }
        if(!linkedList.isEmpty()) {
            throw new CheckedException("分组名称已存在");
        }
        MediumGroupEntity mediumGroupEntity = new MediumGroupEntity();
        mediumGroupEntity.setName(dto.getName());
        mediumGroupEntity.setId(dto.getId());
        mediumGroupEntity.setCorp_id(corpId);
        mediumGroupEntity.setVisibleRange(dto.getVisibleRange());
        String deptIds = null;
        if (dto.getDeptIds() != null) {
            deptIds = dto.getDeptIds().stream().map(String::valueOf).collect(Collectors.joining(","));
        }
        mediumGroupEntity.setDeptIds(deptIds);
        this.baseMapper.updateById(mediumGroupEntity);
        MediumGroupLevel2AddDTO addLevel2DTO = new MediumGroupLevel2AddDTO();
        addLevel2DTO.setChildren(dto.getChildren());
        addLevel2DTO.setDeptIds(dto.getDeptIds());
        addLevel2DTO.setParentId(dto.getId());
        addLevel2DTO.setVisibleRange(dto.getVisibleRange());
        return saveOrUpdateGroupLevel2(addLevel2DTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> deleteMediumGroup(Integer id) {
        R<Boolean> r = this.isDelete(id);
        if (r.getCode() == 0) {
            this.baseMapper.deleteById(id);
            return R.ok(Boolean.TRUE, "删除成功");
        }
        return r;
    }

    @Override
    public List<MediumGroupVO> getMediumGroupList(Integer id) {
        List<MediumGroupEntity> mediumGroupLevel2List = baseMapper.selectList(
                Wrappers.<MediumGroupEntity>lambdaQuery()
                        .eq(MediumGroupEntity::getCorp_id, CorpContextHolder.getCorpId())
                        .eq(BaseEntity::getTenantId, AccountService.getTenantId())
                        .ne(MediumGroupEntity::getParentId, 0)
        );
        if (id != null) {
            List<MediumGroupEntity> mediumGroupEntityList = baseMapper.selectList(
                    Wrappers.<MediumGroupEntity>lambdaQuery()
                    .eq(MediumGroupEntity::getCorp_id, CorpContextHolder.getCorpId())
                    .eq(BaseEntity::getTenantId, AccountService.getTenantId())
                    .eq(MediumGroupEntity::getParentId, 0)
            );
            List<MediumGroupVO> groupVOS = new LinkedList<>();
            for (MediumGroupEntity m : mediumGroupEntityList) {
                m.setCorp_id(CorpContextHolder.getCorpId());
                MediumGroupVO groupVO = new MediumGroupVO();
                if (m.getVisibleRange() == 2) {
                    groupVO.setDepts(depts(m.getDeptIds()));
                }
                BeanUtils.copyProperties(m, groupVO);
                List<MediumGroupDTO> childrens = new ArrayList<>();
                for (MediumGroupEntity entity: mediumGroupLevel2List) {
                    if (m.getId().equals(entity.getParentId())) {
                        MediumGroupDTO dto = new MediumGroupDTO();
                        dto.setId(entity.getId());
                        dto.setParentId(groupVO.getId());
                        dto.setName(entity.getName());
                        dto.setDepts(groupVO.getDepts());
                        dto.setOrder(entity.getOrder());
                        dto.setVisibleRange(groupVO.getVisibleRange());
                        childrens.add(dto);
                    }
                }
                groupVO.setChildren(childrens);
                groupVOS.add(groupVO);
            }
            MediumGroupVO groupVO = new MediumGroupVO();
            groupVO.setId(0);
            groupVO.setParentId(0);
            groupVO.setName("全部分组");
            groupVO.setVisibleRange(1);
            groupVOS.add(groupVO);
            groupVOS.sort(Comparator.comparing(MediumGroupVO::getId));
            return groupVOS;
        } else {
            Integer corpId = CorpContextHolder.getCorpId();
            List<MediumGroupEntity> mediumGroupEntityList = this.getMediumGroupsByCorpId(corpId);
            List<MediumGroupVO> groupVOS = new LinkedList<>();

            for (MediumGroupEntity m : mediumGroupEntityList) {
                MediumGroupVO groupVO = new MediumGroupVO();
                if (m.getVisibleRange() == 2) {
                    groupVO.setDepts(depts(m.getDeptIds()));
                }
                BeanUtils.copyProperties(m, groupVO);
                List<MediumGroupDTO> childrens = new ArrayList<>();
                for (MediumGroupEntity entity: mediumGroupLevel2List) {
                    if (m.getId().equals(entity.getParentId())) {
                        MediumGroupDTO dto = new MediumGroupDTO();
                        dto.setId(entity.getId());
                        dto.setParentId(groupVO.getId());
                        dto.setName(entity.getName());
                        dto.setDepts(groupVO.getDepts());
                        dto.setOrder(entity.getOrder());
                        dto.setVisibleRange(groupVO.getVisibleRange());
                        childrens.add(dto);
                    }
                }
                groupVO.setChildren(childrens);
                groupVOS.add(groupVO);
            }
            MediumGroupVO groupVO = new MediumGroupVO();
            groupVO.setId(0);
            groupVO.setParentId(0);
            groupVO.setName("全部分组");
            groupVO.setVisibleRange(1);
            groupVOS.add(groupVO);
            groupVOS.sort(Comparator.comparing(MediumGroupVO::getId));
            return groupVOS;
        }
    }

    @Override
    public List<MediumGroupVO> getMediumGroupListWeChat(String WxUserId) {
        WorkEmployeeEntity one = workEmployeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                .eq(WorkEmployeeEntity::getWxUserId, WxUserId)
                .eq(WorkEmployeeEntity::getCorpId, CorpContextHolder.getCorpId()));
        Integer corpId = one.getCorpId();
        Integer departmentId = one.getMainDepartmentId();
        Integer deptId = remoteService.deptId(departmentId);

        List<MediumGroupEntity> mediumGroupEntityList= this.getMediumGroupsByCorpId(corpId);
        List<MediumGroupVO> groupVOS = new LinkedList<>();
        for (MediumGroupEntity m : mediumGroupEntityList) {
            MediumGroupVO groupVO = new MediumGroupVO();
            if (m.getVisibleRange() == 2) {
                if (deptId == null) continue;
                String deptIds = m.getDeptIds();
                if (deptIds != null && !deptIds.isEmpty()) {
                    List<Integer> asList = Arrays.asList(deptIds.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList());
                    if (asList.contains(deptId)) {
                        groupVO.setVisibleRange(m.getVisibleRange());
                        groupVO.setName(m.getName());
                        groupVO.setId(m.getId());
                        groupVO.setParentId(0);
                        groupVOS.add(groupVO);
                    }
                }
            } else {
                BeanUtils.copyProperties(m, groupVO);
                groupVO.setParentId(0);
                groupVOS.add(groupVO);
            }
        }
        List<MediumGroupEntity> mediumGroupLevel2List = baseMapper.selectList(
                Wrappers.<MediumGroupEntity>lambdaQuery()
                        .eq(MediumGroupEntity::getCorp_id, CorpContextHolder.getCorpId())
                        .eq(BaseEntity::getTenantId, AccountService.getTenantId())
                        .ne(MediumGroupEntity::getParentId, 0)
        );
        groupVOS.forEach(s -> {
            List<MediumGroupDTO> childrens = new ArrayList<>();
            inner:
            for (MediumGroupEntity entity: mediumGroupLevel2List) {
                if (s.getId().equals(entity.getParentId())) {
                    if (entity.getVisibleRange() == 2) {
                        if (deptId == null) continue inner;
                        String deptIds = entity.getDeptIds();
                        if (deptIds != null && !deptIds.isEmpty()) {
                            List<Integer> asList = Arrays.asList(deptIds.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList());
                            if (asList.contains(deptId)) {
                                MediumGroupDTO dto = new MediumGroupDTO();
                                dto.setId(entity.getId());
                                dto.setParentId(s.getId());
                                dto.setName(entity.getName());
                                dto.setOrder(entity.getOrder());
                                dto.setVisibleRange(entity.getVisibleRange());
                                childrens.add(dto);
                            }
                        }
                    } else {
                        MediumGroupDTO dto = new MediumGroupDTO();
                        dto.setId(entity.getId());
                        dto.setParentId(s.getId());
                        dto.setName(entity.getName());
                        dto.setOrder(entity.getOrder());
                        dto.setVisibleRange(entity.getVisibleRange());
                        childrens.add(dto);
                    }
                }
            }
            s.setChildren(childrens);
        });
        groupVOS.sort(Comparator.comparing(MediumGroupVO::getId));
        return groupVOS;
    }

    @Override
    public R<List<MediumGroupVO>> getMediumGroupByDept(Integer id) {
        List<MediumGroupDepartmentEntity> entities = mediumGroupDepartmentService.getBaseMapper().selectList(Wrappers.<MediumGroupDepartmentEntity>lambdaQuery()
                .eq(MediumGroupDepartmentEntity::getDeptId, id));
        Integer[] list = new Integer[entities.size()];
        int i = 0;
        for (MediumGroupDepartmentEntity m:entities) {
            list[i] = m.getMediumGroupId();
            i++;
        }
        if (entities.isEmpty()){
            return R.ok();
        }
        List<MediumGroupEntity> mediumGroupEntityList = baseMapper.selectList(Wrappers.<MediumGroupEntity>lambdaQuery()
                .eq(MediumGroupEntity::getCorp_id, CorpContextHolder.getCorpId())
                .eq(BaseEntity::getTenantId, AccountService.getTenantId())
                .in(MediumGroupEntity::getId, list));
        List<MediumGroupVO> groupVOS = new LinkedList<>();
        for (MediumGroupEntity m:mediumGroupEntityList) {
            m.setCorp_id(CorpContextHolder.getCorpId());
            MediumGroupVO groupVO = new MediumGroupVO();
            if (m.getVisibleRange() == 2) {
//                List<Integer> lists = new LinkedList<>();
//                List<String> list1 = new LinkedList<>();
//                List<MediumGroupDepartmentEntity> entityList = mediumGroupDepartmentService.list(
//                        Wrappers.<MediumGroupDepartmentEntity>lambdaQuery()
//                                .eq(MediumGroupDepartmentEntity::getMediumGroupId, m.getId()));
//                for (MediumGroupDepartmentEntity s : entityList) {
//                    WorkDeptEntity byId = deptService.getById(s.getDeptId());
//                    lists.add(byId.getId());
//                    list1.add(byId.getName());
//                }
//                groupVO.setDeptEntities(lists);
//                groupVO.setDeptEntitiesText(list1);
            }
            BeanUtils.copyProperties(m,groupVO);
            groupVOS.add(groupVO);
        }
        MediumGroupVO groupVO = new MediumGroupVO();
        groupVO.setId(0);
        groupVO.setName("全部分组");
        groupVO.setVisibleRange(1);
        groupVOS.add(groupVO);
        groupVOS.sort(Comparator.comparing(MediumGroupVO::getId));
        return R.ok(groupVOS);
    }

    @Override
    public R<Boolean> isDelete(Integer id) {
        Integer count = mediumService.count(
                Wrappers.<MediumEnyity>lambdaQuery()
                .eq(MediumEnyity::getMediumGroupId, id)
                .eq(MediumEnyity::getDelFlag, 0)
        );
        if (!(count == null || count == 0)) {
            return R.failed("该分组下还有未删除话术，须先将该分组下话术删除干净后才可删除分组");
        }
        count = this.count(
                Wrappers.<MediumGroupEntity>lambdaQuery()
                        .eq(MediumGroupEntity::getParentId, id)
                        .eq(MediumGroupEntity::getDelFlag, 0)
        );
        if (!(count == null || count == 0)) {
            return R.failed("该分组下还有未删除下级话术分组，须先将该分组下级话术分组删除干净后才可删除分组");
        }
        return R.ok(Boolean.TRUE, "该分组下已没有下级分组或话术，可以删除");
    }

    @Override
    public R<Boolean> updateGroupName(Integer id, String name) {
        MediumGroupEntity entity = this.baseMapper.selectById(id);
        Integer parentId = entity.getParentId();
        Integer count = this.count(
                Wrappers.<MediumGroupEntity>lambdaQuery()
                .eq(MediumGroupEntity::getDelFlag, 0)
                .eq(MediumGroupEntity::getName, name)
                .eq(MediumGroupEntity::getParentId, parentId)
        );
        if (!(count == null || count == 0)) {
            return R.failed("当前一级分组下已存在该二级分组名称");
        }
        entity.setName(name);
        this.updateById(entity);
        return R.ok(Boolean.TRUE, "修改成功");
    }

    @Override
    public R<Boolean> saveChildren(Integer parentId, String name) {
        Integer corpId = CorpContextHolder.getCorpId();
        MediumGroupEntity parentGroup = this.getById(parentId);
        if (parentGroup.getParentId() != null && parentGroup.getParentId() != 0) {
            return R.failed("当前分组非一级分组,不可创建子分组");
        }
        Integer count = this.count(
                Wrappers.<MediumGroupEntity>lambdaQuery()
                        .eq(MediumGroupEntity::getDelFlag, 0)
                        .eq(MediumGroupEntity::getCorp_id, corpId)
                        .eq(MediumGroupEntity::getName, name)
                        .eq(MediumGroupEntity::getParentId, parentId)
        );
        if (!(count == null || count == 0)) {
            return R.failed("当前一级分组下已存在该二级分组名称");
        }
        count = this.count(
                Wrappers.<MediumGroupEntity>lambdaQuery()
                        .eq(MediumGroupEntity::getDelFlag, 0)
                        .eq(MediumGroupEntity::getCorp_id, corpId)
                        .eq(MediumGroupEntity::getParentId, parentId)
        );
        MediumGroupEntity newGroup = new MediumGroupEntity();
        newGroup.setParentId(parentGroup.getId());
        newGroup.setName(name);
        newGroup.setVisibleRange(parentGroup.getVisibleRange());
        newGroup.setDeptIds(parentGroup.getDeptIds());
        newGroup.setCorp_id(corpId);
        newGroup.setOrder(count == null ? 1 : count + 1);
        this.baseMapper.insert(newGroup);
        return R.ok(Boolean.TRUE, "新增成功");
    }

    private List<Map<String, Object>> depts(String deptIds) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (StringUtils.isNotBlank(deptIds)) {
            List<Integer> asList = Arrays.asList(deptIds.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList());
            list = remoteService.depts(asList);
        }
        return list;
    }

}
